--
-- 03/06/2012
-- demouc_m && dourle_a
--

-------------------------------------------------------------
-- Load modules

SYSTEM = os.execute

require('obj.utils')
require('obj.c')
require('obj.callback')
require('obj.stringExtend')
require('obj.diff')

DIR = "norme/"
SEP = "//"
FILE_LIST = DIR .. SEP .. "file"

SYSTEM("mkdir " .. DIR)
SYSTEM("find . -name \"*.[ch]\"  | sort > " .. FILE_LIST)

FILZ = io.open(FILE_LIST ,"r")

FUNCS = {}
FUNC_CALL = {}
TYPES = {}
TABCHECK = {}
WARN = {}

FILE = FILZ:read("*line") 
while FILE ~= nil do
   TABCHECK[FILE] = {}
   WARN[FILE] = {}   
   FILES = {}
   FUNCTION = nil
   FUNCTION_LEN = nil
   ASSIGN = nil
   STRUCT = nil
   FUNC_DEF = nil
   static = false
   include = false
   include_perso = false
   include_double = 0
   include_d = false
   LINE = 0


   SYSTEM("uncrustify -l C -c defaults.cfg -f " .. FILE .. " -o " .. DIR .. FILE ..".out -p " .. DIR .. FILE ..".rest")
   SYSTEM("diff -T --unchanged-line-format=\"\" --old-line-format=\"IN:%dn:%L\" --new-line-format=\"OUT:%dn: %L\" " .. FILE .. " " .. DIR .. FILE .. ".out > " .. DIR .. FILE .. ".diff")

   rest = io.open(DIR .. FILE .. ".rest","r")

   local inDebug = false
   local elems = {}

   tmp_funcs = {}
   while true do
      TYPES = {}
      line = rest:read()
      if not line then break end
      if inDebug then
	 line = string.stripChars(line, " ")
	 local res = string.split(line, "]>[")
	 if res and res[1] then table.insert(elems, {line = res[1], type = res[2], parent = res[3], text = res[8]}) end 
      end
      if line == "-=====-" then inDebug = not inDebug end
   end

   for i,v in ipairs(elems) do
      if v.type ~= nil then
	 LINE = v.line
	 if checks[v.type] ~= nil then checks[v.type](v.text, v.parent) end
      end
   end

   for i, v in ipairs(FUNC_CALL) do
      for j, k in ipairs(FUNCS) do
	 if v.id == k.id then table.insert(k.callers, v.file) end
      end
   end

   for i in pairs(TYPES) do
      LINE = TYPES[i].l
      warn("N;The type: " .. i .. " should contain s_ or t_")
   end

   FILE = FILZ:read("*line")
end

-------------------------------------------------------------
-- Post check 

for i, v in ipairs(FUNCS) do
   if tmp_funcs[v.file] == nil then tmp_funcs[v.file] = 0 end
   tmp_funcs[v.file] = tmp_funcs[v.file] + 1
   if not v.static then checkCallers(v) end
end

for i in pairs(tmp_funcs) do
   LINE = 1
   if tmp_funcs[i] > 5 then warnFile(i, "F:A file: contains " .. tmp_funcs[i] .. " functions.") end
end

-------------------------------------------------------------
-- Diff checks

for i in pairs(WARN) do
   IN = io.open(DIR .. i .. ".diff", "r")
   local diffs = {}
   while true do
      local res = readLine(IN)
      if res and res[1] then
	 if res[1] == "IN" then
	    local obj = {i = {}, o = {}}
	    while true do
	       r = readLine(IN)
	       if r ~= nil and r[1] == "IN" then
		  table.insert(obj.i, {l = tonumber(r[2]), t = r[3], f = i}) else break end
	    end
	    while true do
	       if r ~= nil and r[1] == "OUT" then table.insert(obj.o, {l = tonumber(r[2]), t = r[3], f = i}) else break  end
	       r = readLine(IN)
	    end
	    table.insert(diffs, obj)
	 end
      else break end
   end
   IN:close()
   checkDiff(diffs)
end

for i in pairs(WARN) do
   OUT = io.open(i, "r")
   local n = 0
   FILE = i
   while true do
      n = n + 1
      LINE = n
      local line = OUT:read()
      if line == nil then break end
      if line:len() > 80 and not line:starts("**") then
	 table.insert(WARN[i], {l = n, m = "L;Line longer than 80 characters"})
      end
      if checkInclude(line) == VRAI and  not string.find(line, '\t') then
	 warn("I;No indentation in #include.")
      end
      if checkStruct(line) == VRAI and  not string.find(line, '\t') then
	 warn("I;No indentation in trpedef or struct.")
      end
      if checkDefine(line) == VRAI and  not string.find(line, '\t') then
	 --warn("I;No indentation in #define.")
      end
      if line:len() > 6 and checkFuncProto(line) == VRAI then
	 warn("I;No indentation in function definition.")
      elseif TABCHECK[FILE][tostring(LINE)] ~= nil and not string.find(line, '\t') then
	 warn("I;No indentation in var definition.")
      end
   end
   OUT:close()
end

-------------------------------------------------------------
-- Write warn file for display
FILZ = io.open(FILE_LIST .. "tmp" ,"w")
for i in pairs(WARN) do
   local n = 0
   OUT = io.open(DIR .. i .. ".warn", "w")
   for j,k in ipairs(WARN[i]) do
      n = n + 1
      OUT:write(k.l .. ";" .. k.m .. "\n")
   end
   OUT:close()
   FILZ:write(i .. ";" .. n .. "\n")
end
FILZ:close()

SYSTEM("cat " .. FILE_LIST .. "tmp" .. " | sort > " .. FILE_LIST)


-- SYSTEM("rm -Rf " .. DIR)